package com.hyperexcel.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @desc: HyperExcel线程池配置
 * @author: Linbizhao
 * @date 2024年08月30日 14:20
 */
@Slf4j
@EnableAsync
@Configuration
public class HyperExecutorConfig implements AsyncConfigurer {

    /** 核心线程数 */
    private static final Integer ASYNC_CORE_THREADS = Runtime.getRuntime().availableProcessors();

    /** 最大线程数 */
    private static final Integer ASYNC_MAX_THREADS = Runtime.getRuntime().availableProcessors() * 2;

    /** 线程队列大小 */
    private static final Integer ASYNC_QUEUE_SIZE = 99999;

    /** 线程池名称前缀 */
    private static final String ASYNC_THREAD_PREFIX = "HyperExcel-Async-Pool-";

    @Override
    @Bean("asyncTaskExecutor")
    public Executor getAsyncExecutor() {
        // 定义线程池
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(ASYNC_CORE_THREADS);
        // 线程池最大线程数
        executor.setMaxPoolSize(ASYNC_MAX_THREADS);
        // 线程池队列最大线程数
        executor.setQueueCapacity(ASYNC_QUEUE_SIZE);
        // 线程池名称前缀
        executor.setThreadNamePrefix(ASYNC_THREAD_PREFIX);
        /*
         * 拒绝策略，默认是AbortPolicy
         *
         * AbortPolicy：丢弃任务并直接抛出RejectedExecutionException异常
         * CallerRunsPolicy：交由调用方线程运行，比如 main 线程
         * DiscardPolicy：丢弃任务但不抛出异常
         * DiscardOldestPolicy：丢弃队列中最老的任务程序，然后重试
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new HyperAsyncExceptionHandler();
    }

    /**
     * 异步方法执行的过过程中抛出
     */
    static class HyperAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable ex, Method method, Object... params) {
            log.error("异步线程池执行异常，具体详情:{}", ExceptionUtils.getStackTrace(ex));
        }
    }

    @Bean("customBusinessTaskExecutor")
    public ThreadPoolTaskExecutor customBusinessTaskExecutor() {
        int core = Runtime.getRuntime().availableProcessors();
        int corePoolSize = core * 2;
        int maxPoolSize = corePoolSize * 2;
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(ASYNC_QUEUE_SIZE);
        executor.setThreadNamePrefix("customBusinessTaskExecutor-");
        executor.initialize();
        return executor;
    }

    @Bean("asyncMessageHandlerExecutor")
    public ThreadPoolTaskExecutor asyncMessageHandlerExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(ASYNC_CORE_THREADS * 3);
        executor.setMaxPoolSize(ASYNC_CORE_THREADS * 6);
        executor.setQueueCapacity(ASYNC_QUEUE_SIZE);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setThreadNamePrefix("asyncMessageHandlerExecutor-");
        executor.initialize();
        return executor;
    }
}
